using System.Text;

namespace PmSoft.Core.Http;

/// <summary>
/// HTTP 请求客户端接口，提供基本的 HTTP 请求方法
/// </summary>
public interface IHttpClient
{
	/// <summary>
	/// 设置单个请求头
	/// </summary>
	/// <param name="name">请求头名称</param>
	/// <param name="value">请求头值</param>
	/// <returns>返回当前实例，以便链式调用</returns>
	IHttpClient WithHeader(string name, string value);

	/// <summary>
	/// 设置多个请求头
	/// </summary>
	/// <param name="headers">请求头字典，包含多个头名称和值</param>
	/// <returns>返回当前实例，以便链式调用</returns>
	IHttpClient WithHeaders(IDictionary<string, string> headers);

	/// <summary>
	/// 设置用户代理（User-Agent）字符串
	/// </summary>
	/// <param name="userAgent">用户代理字符串</param>
	/// <returns>返回当前实例，以便链式调用</returns>
	IHttpClient WithUserAgent(string userAgent);

	/// <summary>
	/// 设置 HTTP 请求的超时时间
	/// </summary>
	/// <param name="timeout">超时时间（秒）</param>
	/// <returns>返回当前实例，以便链式调用</returns>
	IHttpClient WithTimeout(int timeout);

	/// <summary>
	/// 设置 Bearer 认证令牌
	/// </summary>
	/// <param name="token">认证令牌</param>
	/// <returns>返回当前实例，以便链式调用</returns>
	IHttpClient WithBearerToken(string token);

	/// <summary>
	/// 发送 GET 请求并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="queryParams">查询参数（可选）</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	T Get<T>(string url, object? queryParams = null);

	/// <summary>
	/// 异步发送 GET 请求并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="queryParams">查询参数（可选）</param>
	/// <param name="cancellationToken">取消请求的令牌（可选）</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	Task<T> GetAsync<T>(string url, object? queryParams = null, CancellationToken cancellationToken = default);

	/// <summary>
	/// 发送 GET 请求并返回字符串
	/// </summary>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="queryParams">查询参数（可选）</param>
	/// <returns>返回字符串内容</returns>
	string GetString(string url, object? queryParams = null);

	/// <summary>
	/// 异步发送 GET 请求并返回字符串
	/// </summary>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="queryParams">查询参数（可选）</param>
	/// <param name="cancellationToken">取消请求的令牌（可选）</param>
	/// <returns>返回字符串内容</returns>
	Task<string> GetStringAsync(string url, object? queryParams = null, CancellationToken cancellationToken = default);

	/// <summary>
	/// 发送 POST 请求并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="data">POST 请求的数据</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	T Post<T>(string url, object? data = null);

	/// <summary>
	/// 异步发送 POST 请求并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="data">POST 请求的数据</param>
	/// <param name="cancellationToken">取消请求的令牌（可选）</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	Task<T> PostAsync<T>(string url, object? data = null, CancellationToken cancellationToken = default);

	/// <summary>
	/// 发送 POST 请求并返回字符串
	/// </summary>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="data">POST 请求的数据</param>
	/// <returns>返回字符串内容</returns>
	string PostString(string url, object? data = null);

	/// <summary>
	/// 异步发送 POST 请求并返回字符串
	/// </summary>
	/// <param name="url">请求的 URL 地址</param>
	/// <param name="data">POST 请求的数据</param>
	/// <param name="cancellationToken">取消请求的令牌（可选）</param>
	/// <returns>返回字符串内容</returns>
	Task<string> PostStringAsync(string url, object? data = null, CancellationToken cancellationToken = default);

	/// <summary>
	/// 上传单个文件并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">上传的 URL 地址</param>
	/// <param name="filePath">文件的路径</param>
	/// <param name="fileParameterName">文件参数名称（默认为 "file"）</param>
	/// <param name="additionalData">额外的请求数据（可选）</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	T UploadFile<T>(string url, string filePath, string fileParameterName = "file", IDictionary<string, string>? additionalData = null);

	/// <summary>
	/// 异步上传单个文件并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">上传的 URL 地址</param>
	/// <param name="filePath">文件的路径</param>
	/// <param name="fileParameterName">文件参数名称（默认为 "file"）</param>
	/// <param name="additionalData">额外的请求数据（可选）</param>
	/// <param name="cancellationToken">取消请求的令牌（可选）</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	Task<T> UploadFileAsync<T>(string url, string filePath, string fileParameterName = "file", IDictionary<string, string>? additionalData = null, CancellationToken cancellationToken = default);

	/// <summary>
	/// 上传多个文件并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">上传的 URL 地址</param>
	/// <param name="filePaths">文件路径集合</param>
	/// <param name="fileParameterName">文件参数名称（默认为 "files"）</param>
	/// <param name="additionalData">额外的请求数据（可选）</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	T UploadFiles<T>(string url, IEnumerable<string> filePaths, string fileParameterName = "files", IDictionary<string, string>? additionalData = null);

	/// <summary>
	/// 异步上传多个文件并返回指定类型的对象
	/// </summary>
	/// <typeparam name="T">返回的数据类型</typeparam>
	/// <param name="url">上传的 URL 地址</param>
	/// <param name="filePaths">文件路径集合</param>
	/// <param name="fileParameterName">文件参数名称（默认为 "files"）</param>
	/// <param name="additionalData">额外的请求数据（可选）</param>
	/// <param name="cancellationToken">取消请求的令牌（可选）</param>
	/// <returns>返回泛型 T 类型的数据</returns>
	Task<T> UploadFilesAsync<T>(string url, IEnumerable<string> filePaths, string fileParameterName = "files", IDictionary<string, string>? additionalData = null, CancellationToken cancellationToken = default);

	/// <summary>
	/// 下载文件到指定路径
	/// </summary>
	/// <param name="url">文件的下载 URL</param>
	/// <param name="saveFilePath">保存文件的路径</param>
	void DownloadFile(string url, string saveFilePath);

	/// <summary>
	/// 异步下载文件到指定路径
	/// </summary>
	/// <param name="url">文件的下载 URL</param>
	/// <param name="saveFilePath">保存文件的路径</param>
	/// <param name="progress">下载进度回调（可选）</param>
	/// <param name="cancellationToken">取消请求的令牌（可选）</param>
	Task DownloadFileAsync(string url, string saveFilePath, IProgress<double>? progress = null, CancellationToken cancellationToken = default);
}
